﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Reap.Common.Runtime.Dependency.Ninject;
using Reap.Common.Runtime;
using Reap.Common.Runtime.Dependency;
using DependencyAttribute = System.Runtime.CompilerServices.DependencyAttribute;

namespace Reap.Common.Runtime.Dependency.Ninject {
	/// <summary>
	/// 引擎服务类
	/// </summary>
	public class NinjectEngine : IEngine {

		#region Properties

		public IContainerManager ContainerManager {
			get;
			private set;
		}

		public ITypeFinder TypeFinder {
			get;
			private set;
		}
		#endregion

		#region .ctor
		public NinjectEngine()
			: this(new WebAppTypeFinder() { AssemblySkipLoadingPattern = "System\\." }) {

		}
		public NinjectEngine(ITypeFinder typeFinder)
			: this(typeFinder, new ContainerManager()) { }
		public NinjectEngine(ITypeFinder typeFinder, ContainerManager containerManager) {
			if (typeFinder == null) {
				throw new ArgumentException("没有反射类查找器");
			}
			this.TypeFinder = typeFinder;
			this.ContainerManager = containerManager;
			InitializeContainer();
		}
		#endregion

		#region Methods
		/// <summary>
		/// 初始化所有的特性服务类注册到容器中
		/// </summary>
		private void InitializeContainer() {
			var attrDependency = new DependencyAttributeRegistrator(this.TypeFinder, this.ContainerManager);
			attrDependency.RegisterServices();
		}

		#region Resolve
		public T Resolve<T>(params Parameter[] parameters) where T : class {
			return ContainerManager.Resolve<T>(null, parameters);
		}

		public T Resolve<T>(string name, params Parameter[] parameters) where T : class {
			return ContainerManager.Resolve<T>(name, parameters);
		}

		public object Resolve(Type type, params Parameter[] parameters) {
			return ContainerManager.Resolve(type, null, parameters);
		}

		public object Resolve(Type type, string name, params Parameter[] parameters) {
			return ContainerManager.Resolve(type, name, parameters);
		}
		#endregion

		#region TryResolve
		public T TryResolve<T>(params Parameter[] parameters) where T : class {
			return ContainerManager.TryResolve<T>(null, parameters);
		}

		public T TryResolve<T>(string name, params Parameter[] parameters) where T : class {
			return ContainerManager.TryResolve<T>(name, parameters);
		}

		public object TryResolve(Type type, params Parameter[] parameters) {
			return ContainerManager.TryResolve(type, null, parameters);
		}

		public object TryResolve(Type type, string name, params Parameter[] parameters) {
			return ContainerManager.TryResolve(type, name, parameters);
		}
		#endregion

		#region ResolveAll
		public IEnumerable<object> ResolveAll(Type serviceType) {
			return ContainerManager.ResolveAll(serviceType);
		}

		public IEnumerable<T> ResolveAll<T>() {
			return ContainerManager.ResolveAll<T>();
		}
		#endregion

		#endregion
	}
}
